using System;
using System.Reflection;
using System.IO;
using System.Threading;
using System.Xml;
using System.Collections;
using SharpObjects.Configuration;
using SharpObjects.Configuration.ConfigurationProviders;
using System.Web;
using SharpObjects.Configuration.Services;
using SharpObjects.Interfaces;
using SharpObjects.PathMapping;

namespace SharpObjects.Logging.LogTargets 
{
	public class TextFileLogTarget : FileLogTargetBase
	{
   		protected TextWriter textWriter = null;
		protected FileStream fileStream = null;

        #region CONSTRUCTORS

        public TextFileLogTarget()
        {
		}

        public TextFileLogTarget(XmlElement initializationElement)
        {
            Initialize(initializationElement);
        }

		public TextFileLogTarget(string logDirectory)
            : base(logDirectory)
        {
		}

	    public TextFileLogTarget(string logDirectory, string logFileNameBase)
            : base(logDirectory, logFileNameBase)
        {
		}

		public TextFileLogTarget(string logDirectory, string logFileNameBase, string extension)
            : base(logDirectory, logFileNameBase, extension)
        {
		}

		public TextFileLogTarget(string logDirectory, string logFileNameBase, string extension, int nMaxSize)
            : base(logDirectory, logFileNameBase, extension, nMaxSize)
        {
		}

        #endregion //CONSTRUCTORS

        public override void Initialize(XmlElement initializationElement)
        {
            base.Initialize(initializationElement);

            IConfigurationProvider init = new XmlConfigurationProvider(initializationElement);

            this.formatter = init.GetObject<ILogFormatter>(formatterTag, (ILogFormatter)null);

            if (this.formatter == null)
            {
                string formatterId = init.GetString(formatter_id_tag);
                this.formatter = ConfigurableServiceFactory.Instance.GetService<ILogFormatter>(formatterId);
            }
        }

		protected void Open()
		{
			if(this.fileStream == null || this.textWriter == null)
			{
				Close();

				if(!File.Exists(this.logFileName))
				{
					CreateNew();
				}

				this.fileStream = new FileStream(this.logFileName, FileMode.Append, FileAccess.Write, FileShare.ReadWrite);
				this.fileStream.Seek(0, SeekOrigin.End);
				this.textWriter = new StreamWriter(this.fileStream);
			}
		}

		protected override void Close()
		{
			if(this.textWriter != null)
			{
				this.textWriter.Close();
				this.textWriter = null;
			}

			if(this.fileStream != null)
			{
				this.fileStream.Close();
				this.fileStream = null;
			}
		}
		
		protected override void WriteToLog(ILogEntry logEntry)
		{
			try
			{
				Open();

				if(this.fileStream.Length >= this.maxSize)
				{
					Close();
					Rename();
					CreateNew();
					Open();
                    CleanupHistory();
				}

				if(this.textWriter != null)
				{
                    string logMessage = this.formatter.ApplyFormat(logEntry);

                    if(this.seekToEndBeforeWrite)
                    {
                        this.fileStream.Seek(0, SeekOrigin.End);
                    }

                    this.textWriter.Write(logMessage);
					this.textWriter.Flush();
				}
			}
			catch(Exception exception)
			{
				Close();
                Log.AddErrorMessage(exception);
			}            
		}
	}
}
